
#pragma once

namespace gfx
{
    typedef void* BHandle;
} // namespace gfx

namespace gfx
{
    class IApplication
    {
        public:

            virtual ~IApplication();

        public:

            bool OnStartup();
            bool OnShutdown();
            bool OnCreateTextures();
            bool OnReleaseTextures();
            bool OnCreateMeshes();
            bool OnReleaseMeshes();
            bool OnCreateObjects();
            bool OnReleaseObjects();
            bool OnResize(int _Width, int _Height);
            bool OnKeyEvent(unsigned int _Key, bool _IsKeyDown, bool _IsAltDown);
            bool OnMouseEvent(int _X, int _Y, int _Button, bool _IsButtonDown, bool _IsDoubleClick, int _WheelDelta);
            bool OnUpdate();
            bool OnFrame();

        private:

            virtual bool InternOnStartup();
            virtual bool InternOnShutdown();
            virtual bool InternOnCreateTextures();
            virtual bool InternOnReleaseTextures();
            virtual bool InternOnCreateMeshes();
            virtual bool InternOnReleaseMeshes();
            virtual bool InternOnCreateObjects();
            virtual bool InternOnReleaseObjects();
            virtual bool InternOnResize(int _Width, int _Height);
            virtual bool InternOnKeyEvent(unsigned int _Key, bool _IsKeyDown, bool _IsAltDown);
            virtual bool InternOnMouseEvent(int _X, int _Y, int _Button, bool _IsButtonDown, bool _IsDoubleClick, int _WheelDelta);
            virtual bool InternOnUpdate();
            virtual bool InternOnFrame();
    };
} // namespace gfx

namespace gfx
{
    bool OpenWindow(int _Width, int _Height, const char* _pTitle);
    bool CloseWindow();

    bool StartupDirectX();
    bool ShutdownDirectX();

    bool RunApplication(IApplication* _pApplication);

    bool SetDepthTest(bool _Flag);
    bool SetWireFrame(bool _Flag);

    void SetClearColor(const float* _pColor);
} // namespace gfx

namespace gfx
{
    bool CreateTexture(const char* _pPath, BHandle* _ppTexture);
    bool ReleaseTexture(BHandle _pTexture);
} // namespace gfx

namespace gfx
{
    bool CreateMesh(const float* _pVertices, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
    bool CreateMesh(const float* _pVertices, const float* _pNormals, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
    bool CreateColoredMesh(const float* _pVertices, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
    bool CreateColoredMesh(const float* _pVertices, const float* _pNormals, const float* _pColors, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle* _ppMesh);
    bool CreateTexturedMesh(const float* _pVertices, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh);
    bool CreateTexturedMesh(const float* _pVertices, const float* _pNormals, const float* _pTexCoords, int _NumberOfVertices, const int* _pIndices, int _NumberOfIndices, BHandle _pTexture, BHandle* _ppMesh);
    bool ReleaseMesh(BHandle _pMesh);
} // namespace gfx

namespace gfx
{
    bool CreateObject(BHandle _pMesh, BHandle* _ppObject);
    bool ReleaseObject(BHandle _pObject);
} // namespace gfx

namespace gfx
{
    bool DrawObject(BHandle _pObject);
} // namespace gfx

namespace gfx
{
    void SetWorldMatrix(BHandle _pObject, const float* _pMatrix);
    void SetViewMatrix(const float* _pMatrix);
    void SetProjectionMatrix(const float* _pMatrix);
} // namespace gfx

namespace gfx
{
    void SetLightPosition(const float* _pPosition);
    void SetLightColor(const float* _pAmbientColor, const float* _pDiffuseColor, const float* _pSpecularColor, float _SpecularExponent);
} // namespace gfx

namespace gfx
{
    float* GetNormalizedVector(const float* _pVector, float* _pResultVector);
    float* TransformVector(const float* _pVector, const float* _pMatrix, float* _pResultVector);

    float* MulMatrix(const float* _pLeftMatrix, const float* _pRightMatrix, float* _pResultMatrix);

    float* GetTranslationMatrix(float _X, float _Y, float _Z, float* _pResultMatrix);
    float* GetScaleMatrix(float _Scalar, float* _pResultMatrix);
    float* GetScaleMatrix(float _ScalarX, float _ScalarY, float _ScalarZ, float* _pResultMatrix);
    float* GetRotationXMatrix(float _Degrees, float* _pResultMatrix);
    float* GetRotationYMatrix(float _Degrees, float* _pResultMatrix);
    float* GetRotationZMatrix(float _Degrees, float* _pResultMatrix);

    float* GetViewMatrix(float* _pEye, float* _pAt, float* _pUp, float* _pResultMatrix);

    float* GetProjectionMatrix(float _FieldOfViewY, float _AspectRatio, float _Near, float _Far, float* _pResultMatrix);
} // namespace gfx

